package model

import (
	"database/sql/driver"
	"encoding/json"
	"time"
)

// Article RSS文章模型
// 对应数据库表: articles
type Article struct {
	// ==================== 主键 ====================
	ID int64 `gorm:"primaryKey;autoIncrement" json:"id"`

	// ==================== 关联字段 ====================
	// FeedID 所属订阅源ID (外键)
	FeedID int64 `gorm:"not null;index:idx_feed_id;column:feed_id" json:"feed_id"`

	// Feed 所属订阅源 (关联对象,按需加载)
	Feed *Feed `gorm:"foreignKey:FeedID" json:"feed,omitempty"`

	// ==================== 文章基本信息(来自 RSS) ====================
	// GUID 文章唯一标识 (RSS guid,与 FeedID 组成联合唯一索引)
	GUID string `gorm:"type:varchar(500);not null;uniqueIndex:uk_feed_guid,priority:2" json:"guid"`

	// Title 文章标题 (必填)
	Title string `gorm:"type:varchar(500);not null" json:"title"`

	// Link 原文链接 (必填)
	Link string `gorm:"type:varchar(1000);not null" json:"link"`

	// Author 作者 (可选)
	Author string `gorm:"type:varchar(200)" json:"author"`

	// PublishedAt 发布时间 (可为 NULL)
	PublishedAt *time.Time `gorm:"column:published_at;index:idx_published_at" json:"published_at"`

	// ==================== 文章内容 ====================
	// Description 文章摘要(原始,来自 RSS)
	Description string `gorm:"type:text" json:"description"`

	// Content 文章正文(HTML)
	Content string `gorm:"type:longtext" json:"content"`

	// ==================== AI 生成内容 ====================
	// AISummary AI 生成的摘要(100-200字)
	AISummary string `gorm:"type:text;column:ai_summary" json:"ai_summary"`

	// AITags AI 生成的标签数组
	// 使用自定义类型存储 JSON 数组
	AITags StringArray `gorm:"type:json;column:ai_tags" json:"ai_tags"`

	// AIGeneratedAt AI 内容生成时间
	AIGeneratedAt *time.Time `gorm:"column:ai_generated_at;index:idx_ai_generated" json:"ai_generated_at"`

	// ==================== 用户操作 ====================
	// IsRead 是否已读 (默认: false)
	IsRead bool `gorm:"default:false;index:idx_is_read;column:is_read" json:"is_read"`

	// IsStarred 是否收藏 (默认: false)
	IsStarred bool `gorm:"default:false;index:idx_is_starred;column:is_starred" json:"is_starred"`

	// UserNote 用户笔记(Markdown 格式)
	UserNote string `gorm:"type:text;column:user_note" json:"user_note"`

	// ==================== 时间戳 ====================
	CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
	UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"`

	// ==================== 关联关系 ====================
	// Tags 文章的标签列表 (多对多)
	Tags []Tag `gorm:"many2many:article_tags" json:"tags,omitempty"`
}

// TableName 指定表名
func (Article) TableName() string {
	return "articles"
}

// ==================== 自定义类型: StringArray ====================
// StringArray 字符串数组,用于存储 JSON 格式的标签
// 实现 driver.Valuer 和 sql.Scanner 接口,支持 GORM 自动转换
type StringArray []string

// Value 实现 driver.Valuer 接口,将 Go 类型转换为数据库类型
// GORM 在写入数据库时调用
func (s StringArray) Value() (driver.Value, error) {
	if s == nil {
		return nil, nil
	}
	// 序列化为 JSON 字符串
	return json.Marshal(s)
}

// Scan 实现 sql.Scanner 接口,将数据库类型转换为 Go 类型
// GORM 在读取数据库时调用
func (s *StringArray) Scan(value interface{}) error {
	if value == nil {
		*s = nil
		return nil
	}

	// 将数据库中的 JSON 字符串反序列化为 []string
	bytes, ok := value.([]byte)
	if !ok {
		return nil
	}

	return json.Unmarshal(bytes, s)
}

// ==================== 业务方法 ====================

// HasAISummary 判断是否有 AI 摘要
func (a *Article) HasAISummary() bool {
	return a.AISummary != "" && a.AIGeneratedAt != nil
}

// MarkRead 标记为已读
func (a *Article) MarkRead() {
	a.IsRead = true
}

// ToggleStar 切换收藏状态
func (a *Article) ToggleStar() {
	a.IsStarred = !a.IsStarred
}

// SetAISummary 设置 AI 摘要
func (a *Article) SetAISummary(summary string, tags []string) {
	a.AISummary = summary
	a.AITags = tags
	now := time.Now()
	a.AIGeneratedAt = &now
}

// GetShortDescription 获取简短描述(用于列表展示)
// 优先使用 AI 摘要,其次使用原始摘要的前 100 字
func (a *Article) GetShortDescription(maxLen int) string {
	if maxLen <= 0 {
		maxLen = 100
	}

	// 优先使用 AI 摘要
	if a.AISummary != "" {
		if len([]rune(a.AISummary)) <= maxLen {
			return a.AISummary
		}
		runes := []rune(a.AISummary)
		return string(runes[:maxLen]) + "..."
	}

	// 使用原始摘要
	if a.Description != "" {
		runes := []rune(a.Description)
		if len(runes) <= maxLen {
			return a.Description
		}
		return string(runes[:maxLen]) + "..."
	}

	return ""
}
